/*
 * Copyright (c) 2010-2013 Ruben Chakhmakhchyan. All rights reserved.
 * 
 * This file contains Original Code and/or Modifications of Original Code
 * as defined in and that are subject to the Eclipse Public License
 * Version 1.0 (the 'License'). You may not use this file except in
 * compliance with the License. Please obtain a copy of the License at
 * http://opensource.org/licenses/EPL-1.0 and read it before using this file.
 */

#include "commontypes.h"
#include "test_model_impl.h"
#include <stdio.h>
// windows
#include <windows.h>
#include <windowsx.h>
#include "result_codes.h"
#include "strings.h"

#pragma warning( disable : 4996 )


// initialize static members
char TestDriverModel::m_modelTypeName[] = "TEST";

#define IMAGE_FOLDER "D:\\pro\\bamboofox\\iatest\\barcode\\undefined\\150-gs\\"


TestDriverModel::TestDriverModel( ImageSite* imageSite, MessageListener* messageListener )
	: m_deviceIndex( 0 ),
	m_resolution( 100 ),
	m_pixelType( PixelType::Rgb ),
	m_colorDepth( 24 ),
	m_dataType( 0 ),
	m_pImageSite( imageSite ),
	m_autoBright( false ),
	m_contrast( 0 ),
	m_messageListener( messageListener ),
	m_connected( false ),
	m_orientation( 0 )
{
}

TestDriverModel::~TestDriverModel()
{
}

bool TestDriverModel::getDevices()
{
	m_devices.clear( false );

	DeviceInfo di = { 0 };

	di.index = 1;
	wchar_t uid[] = L"{00000001-0002-0003-0004-000000000005}";
	wchar_t id[] = L"{00000001-0002-0003-0004-000000000005}\\0001";
	::memcpy( di.id, uid, ( String::GetLength( id ) + 1 ) << 1 );
	::memcpy( di.uid, uid, ( String::GetLength( uid ) + 1 ) << 1 );
	::memcpy( di.productName, L"Test Device N1", ( String::GetLength( L"Test Device N1" ) + 1 ) << 1 );
	::memcpy( di.manufacturer, L"Manufacturer N1", ( String::GetLength( L"Manufacturer N1" ) + 1 ) << 1 );
	::memcpy( di.productFamily, L"Test Product N1", ( String::GetLength( L"Test Product N1" ) + 1 ) << 1 );

	ImagingDevice device( &di );

	m_devices.add( device );

	return true;
}

void TestDriverModel::loadFromFile( char* filename )
{
	FILE *pFile;

	errno_t error = ::fopen_s( &pFile, filename, "rb");

	byte_t* bp = m_buffer;
	size_t read = 0;
	size_t count = 0;

	while( ( count = ::fread( bp, 1, 4096, pFile ) ) > 0 )
	{
		bp += count;
	}
	::fclose( pFile );
	pFile = 0;

	BITMAPFILEHEADER& bfi = *( ( PBITMAPFILEHEADER ) m_buffer );
	size_t sizeBits = bp - ( m_buffer + bfi.bfOffBits );
	size_t size = bp - ( m_buffer + sizeof( BITMAPFILEHEADER ) );
	//byte_t* data = new byte_t[ size ];
	//memcpy( data, m_buffer + sizeof( BITMAPFILEHEADER ), size );

	LPBITMAPINFOHEADER pDIB = ( LPBITMAPINFOHEADER ) ( m_buffer + sizeof( BITMAPFILEHEADER ) );

	//-----------------


	LONG width = pDIB->biWidth;
	LONG height = pDIB->biHeight;

	unsigned int paletteSize = 0;

	switch( pDIB->biBitCount )
	{
	case 1: paletteSize = sizeof( RGBQUAD ) << 1; break;
	case 8: paletteSize = sizeof( RGBQUAD ) << 8; break;
	case 24: break;
	default:
		//assert( 0 ); // not going to work
		throw "WRONG BIT COUNT!!";
		break;
	}

	// calculate the correct size
	size_t lineBitCount = width * pDIB->biBitCount; // number of actual image bits in a scanline
	size_t stride = ( ( lineBitCount + 31 ) & ~31 ) >> 3; // number of bytes in 32-bit aligned scanline
	size_t alignedBytes = stride * height; // size of aligned image data
	size_t lineColorCount = ( ( ( lineBitCount + 7 ) & ~7 ) >> 3 ); // number of bytes in a line
	size_t colorBytes = lineColorCount * height; // size of unaligned image data

	size_t headerSize = sizeof( BITMAPINFOHEADER ) + paletteSize;

	size_t sourceDibSize = headerSize + pDIB->biSizeImage;
	size_t destDibSize = headerSize + alignedBytes;

	bool aligned = ( pDIB->biSizeImage == 0 && pDIB->biCompression != 0 ) || ( pDIB->biSizeImage == alignedBytes );
	bool unaligned = pDIB->biSizeImage == colorBytes;
	bool imageValid = aligned || unaligned;

	// notify the image site
	if ( imageValid )
	{
		Pixels image = { 0 };
		bool result = m_pImageSite->createPixels( pDIB, image );
		m_pImageSite->imageReady( image );
	}
}

static char* files[] = {
	"image-3x-c.bmp",
	"image-3x-cr.bmp",
	"image-3x-cgs.bmp",
	"image-3x-cbw.bmp",
	"image-01-c.bmp",
	"image-02-c.bmp",
	"image-01-c.bmp",
	"image-02-c.bmp",
	"image-01-c.bmp",
	"image-02-c.bmp",
	"image-01-c.bmp",
	"image-02-c.bmp",
	"image-01-c.bmp",
	"image-02-c.bmp",
	"image-01-c.bmp",
	"image-02-c.bmp",
};

ResultCode TestDriverModel::scan()
{
	m_buffer = new byte_t[ 20000000 ];

	char path[ 512 ];
	uint_t folderPathLength = String::GetLength( IMAGE_FOLDER );

	for ( int i = 0; i < 4; i++ )
	{
		::Sleep( 400 );

		::memset( path, 0, 512 );
		::memcpy( path, IMAGE_FOLDER, folderPathLength );

		::strcat( path, files[ i ] );

		loadFromFile( path );
	}

	delete[] m_buffer;

	return ResultCode::Success;
}

bool TestDriverModel::getIsDeviceFeatureSupported( DeviceFeature deviceFeature ) const
{
	switch ( deviceFeature )
	{
	case DeviceFeature::Flatbed: return false; break;
	case DeviceFeature::Feeder: return true; break;
	case DeviceFeature::Duplex: return false; break;
	}
	return false;
}

bool TestDriverModel::getIsPaperSourceFixed() const
{
	return true;
}

BaseCap* TestDriverModel::getCap( uint_t cap )
{
	BaseCap* baseCap = NULL;

	switch ( cap )
	{
	case 0x180c:
		{
			uint_t count = 2;
			int* a = new int[ count ];
			*a = 0;
			*( a + 1 ) = 1;
			baseCap = new IntListCap( cap, count, a, 0, 0 );
		}
		break;

	case 0x1803:
		{
			uint_t count = 4;
			int* a = new int[ count ];
			*a = 75;
			*( a + 1 ) = 100;
			*( a + 2 ) = 150;
			*( a + 3 ) = 200;
			baseCap = new IntListCap( cap, count, a, 0, 0 );
		}
		break;
	}

	return baseCap;
}

ImagingDevice* TestDriverModel::getDevice( int index )
{
	if ( index < 0 || index >= m_devices.count() )
		return NULL;

	return &m_devices[ index ];
}
